package blazingbubble.graphics.lobby;

import blazingbubble.game.ILobbyGameEventListener;
import blazingbubble.graphics.game.IJoinGameListener;
import blazingbubble.lobby.command.LobbyCommandFactory;
import blazingbubble.graphics.IActivable;
import blazingbubble.game.command.GameCommandFactory;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

import moltencore.game.Game;
import org.apache.log4j.Logger;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import java.util.HashMap;

public class LobbyScreen extends JPanel implements IActivable, ActionListener,
		IGameListUpdateListener {
	private static final long serialVersionUID = -5080008587639434265L;



	private Logger logger = Logger.getLogger(LobbyScreen.class);

	private HashMap<Integer, Integer> gameTeamsCountMap = new HashMap<Integer, Integer>();
	private HashMap<Integer, Integer> gameTeamsSizeMap = new HashMap<Integer, Integer>();
	private JTextField loginNameTextField;
//  private JTextField gameNameTextField;
	private JButton gameCreateButton;
	private JButton joinButton;
	private JButton refreshButton;

	private CreateGameOptionsWindow gameOptionsWindow = null;
	private JFrame parentFrame = null;

	private JTable gameTable;
	private DefaultTableModel gameTableModel;
	private HashMap<Integer, Integer> gameTablePortsMap = new HashMap<Integer, Integer>();

	private Container displayArea;

	private LobbyCommandFactory commandFactory;
	private GameCommandFactory gameCommandFactory;
	private ILobbyGameEventListener lobbyGameEventListener;

	private boolean isReceiving = false;
	private IJoinGameListener joinGameListener;

	public LobbyScreen(Container displayArea,
	                   LobbyCommandFactory commandFactory,
	                   GameCommandFactory gameCommandFactory, ILobbyGameEventListener lobbyGameEventListener, JFrame parentFrame) {
		this.displayArea = displayArea;
		this.parentFrame = parentFrame;
		this.commandFactory = commandFactory;
		this.gameCommandFactory = gameCommandFactory;
		this.lobbyGameEventListener = lobbyGameEventListener;

		// Create game
	//	add(new JLabel("GameName: "));
	//	gameNameTextField = new JTextField(CreateGame.GAME_NAME_LENGTH_MAX);
	//	add(gameNameTextField);

		gameCreateButton = new JButton("Create Game");
		gameCreateButton.addActionListener(this);
		add(gameCreateButton);

		// Join Game
		add(new JLabel("PlayerName: "));
		loginNameTextField = new JTextField(
				moltencore.network.protocol.JoinGame.NAME_LENGTH_MAX);
		add(loginNameTextField);

		joinButton = new JButton("Join");
		joinButton.addActionListener(this);
		add(joinButton);

		// Refresh Games

		refreshButton = new JButton("Refresh Games");
		refreshButton.addActionListener(this);
		add(refreshButton);

		// Game Table

		gameTableModel = new DefaultTableModel(null, tableColumnNames);
		gameTable = new JTable(gameTableModel);
		gameTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		add(new JScrollPane(gameTable));
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource().equals(gameCreateButton)) {
			gameOptionsWindow = new CreateGameOptionsWindow(parentFrame, this);
			gameOptionsWindow.setVisible(true);
		} else if (e.getSource().equals(joinButton)) {
			joinGameListener.gameJoined(
					gameTeamsCountMap.get(gameTablePortsMap.get(gameTable.getSelectedRow())),
					gameTeamsSizeMap.get(gameTablePortsMap.get(gameTable.getSelectedRow())));
			lobbyGameEventListener.gameSelected(gameTablePortsMap.get(gameTable.getSelectedRow()));
			gameCommandFactory.getJoinGame().setPlayerName(loginNameTextField.getText());
			gameCommandFactory.getJoinGame().join();
			finishUpdating();
		} else if (e.getSource().equals(refreshButton)) {
			if (isReceiving) {
				finishUpdating();
			} else {
				refreshButton.setText("Stop Refresh");
				isReceiving = true;
				clearTableData();
				commandFactory.getGameList().requestGameList();
			}
		}
	}

	public IJoinGameListener getJoinGameListener() {
		return joinGameListener;
	}

	public void setJoinGameListener(IJoinGameListener l) {
		joinGameListener = l;
	}

	@Override
	public void activate() {
		displayArea.removeAll();
		displayArea.add(this);
		((JPanel) displayArea).updateUI();
	}

	@Override
	public void finishUpdating() {
		isReceiving = false;
		refreshButton.setText("Refresh Games");
	}

	@Override
	public boolean isReceiving() {
		return isReceiving;
	}

	private static final String[] tableColumnNames = {
		"Game Name",
		"Players",
		"Game Mode",
		"b/g/r/b/c/g/w/f/t"};

	@Override
	public void addGame(int gamePort, int currentPlayers, int maxPlayers,
			int normalBubbleCount, boolean ghostBubblesEnabled,
			boolean rainbowBubblesEnabled, boolean blazingBubblesEnabled,
			boolean chainReactionsEnabled, boolean gravityEnabled,
			boolean windEnabled, boolean fieldFlipped, Game.Mode mode,
			boolean teamsEnabled, String gameName) {
		int teamSize = teamsEnabled ? 2 : 1;
		gameTeamsSizeMap.put(gamePort, teamSize);
		gameTeamsCountMap.put(gamePort, maxPlayers / teamSize);
		this.gameTablePortsMap.put(gameTableModel.getRowCount(), gamePort);
		gameTableModel.insertRow(gameTableModel.getRowCount(),
					new Object[] {
				gameName,
				currentPlayers + "/" + maxPlayers,
				mode,
				normalBubbleCount + "/" +
				(ghostBubblesEnabled ? "x" : "o") + "/" +
				(rainbowBubblesEnabled ? "x" : "o") + "/" +
				(blazingBubblesEnabled ? "x" : "o") + "/" +
				(gravityEnabled ? "x" : "o") + "/" +
				(windEnabled ? "x" : "o") + "/" +
				(fieldFlipped ? "x" : "o") + "/" +
				(teamsEnabled ? "x" : "o")});
	//	gameTableModel.fireTableRowsInserted(0,
	//			gameTable.getRowCount() - 1);
	//	gameTable.updateUI();
	}

	private void clearTableData(){
		for (int i = 0; i < gameTableModel.getRowCount(); i++){
			gameTableModel.removeRow(0);
		}
	}

	public void startNewGame(
								String gameName,
								Game.Mode mode,
								int maxPlayers,
								int normalBubblesCount,
								boolean ghostBubblesEnabled,
								boolean rainbowBubblesEnabled,
								boolean blazingBubblesEnabled,
								boolean gravityEnabled,
								boolean windEnabled,
								boolean flippedFieldEnabled,
								boolean teamsEnabled){
		gameCommandFactory.getJoinGame().setPlayerName(loginNameTextField.getText());
		commandFactory.getCreateGame().createGame(
				gameName,
				mode,
				maxPlayers,
				normalBubblesCount,
				ghostBubblesEnabled,
				rainbowBubblesEnabled,
				blazingBubblesEnabled,
				gravityEnabled,
				windEnabled,
				flippedFieldEnabled,
				teamsEnabled);
		int teamSize = teamsEnabled ? 2 : 1;
		joinGameListener.gameJoined(maxPlayers / teamSize, teamSize);
	}
}
